{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Role tags\n",
    "\n",
    "This notebook shows how to use the role tags in Guidance. While each chat model may define their own special tokens, the role tags can be used across all chat models. A role is specified using the `{{#role \"role_name\"}}...{{/role}}` command. Since ChatGPT uses three roles, we give convenience commands for each role: `{{#user}}...{{/user}}`, `{{#assistant}}...{{/assistant}}`, and `{{#system}}...{{/system}}`. These commands are equivalent to `{{#role \"user\"}}...{{/role}}`, `{{#role \"assistant\"}}...{{/role}}`, and `{{#role \"system\"}}...{{/role}}`, respectively.\n",
    "\n",
    "The follow example demonstrates how to use the role tags. Note that the white space outside the role tags is ignored, and that the `~` character is a standard syntax for indicating that the white space before or after the command (depending on the location of the `~`) should be ignored."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div id=\"guidance-stop-button-17eb2469-4a39-4409-941f-a533bcedfded\" style=\"cursor: pointer; margin: 0px; display: none; float: right; padding: 3px; border-radius: 4px 4px 4px 4px; border: 0px solid rgba(127, 127, 127, 1); padding-left: 10px; padding-right: 10px; font-size: 13px; background-color: rgba(127, 127, 127, 0.25);\">Stop program</div><div id=\"guidance-content-17eb2469-4a39-4409-941f-a533bcedfded\"><pre style='margin: 0px; padding: 0px; padding-left: 8px; margin-left: -8px; border-radius: 0px; border-left: 1px solid rgba(127, 127, 127, 0.2); white-space: pre-wrap; font-family: ColfaxAI, Arial; font-size: 15px; line-height: 23px;'><span style='background-color: rgba(0, 138.56128016, 250.76166089, 0.25); display: inline;' title='{{#system~}}\n",
       "You are a helpful assistant.\n",
       "{{~/system}}'><div style='display: flex; border-bottom: 1px solid rgba(127, 127, 127, 0.2); align-items: center;'><div style='flex: 0 0 80px; opacity: 0.5;'>system</div><div style='flex-grow: 1; padding: 5px; padding-top: 10px; padding-bottom: 10px; margin-top: 0px; white-space: pre-wrap; margin-bottom: 0px;'>You are a helpful assistant.</div></div></span><span style='background-color: rgba(0, 138.56128016, 250.76166089, 0.25); display: inline;' title='{{#user~}}\n",
       "I want to {{goal}}.\n",
       "\n",
       "Here is my plan:\n",
       "{{parse_best prosandcons options}}\n",
       "Please elaborate on this plan, and tell me how to best accomplish it.\n",
       "{{~/user}}'><div style='display: flex; border-bottom: 1px solid rgba(127, 127, 127, 0.2); align-items: center;'><div style='flex: 0 0 80px; opacity: 0.5;'>user</div><div style='flex-grow: 1; padding: 5px; padding-top: 10px; padding-bottom: 10px; margin-top: 0px; white-space: pre-wrap; margin-bottom: 0px;'>I want to <span style='background-color: rgba(0, 138.56128016, 250.76166089, 0.25); display: inline;' title='{{goal}}'>read more books</span>.\n",
       "Here is my plan:\n",
       "<span style='background-color: rgba(0, 138.56128016, 250.76166089, 0.25); display: inline;' title='{{parse_best prosandcons options}}'>Join a book club to stay motivated and accountable for reading more books.</span>\n",
       "Please elaborate on this plan, and tell me how to best accomplish it.</div></div></span><span style='background-color: rgba(0, 138.56128016, 250.76166089, 0.25); display: inline;' title='{{#assistant~}}\n",
       "{{gen &#x27;plan&#x27; max_tokens=500}}\n",
       "{{~/assistant}}'><div style='display: flex; border-bottom: 1px solid rgba(127, 127, 127, 0.2); align-items: center;'><div style='flex: 0 0 80px; opacity: 0.5;'>assistant</div><div style='flex-grow: 1; padding: 5px; padding-top: 10px; padding-bottom: 10px; margin-top: 0px; white-space: pre-wrap; margin-bottom: 0px;'><span style='background-color: rgba(0, 165, 0, 0.25); opacity: 1.0; display: inline;' title='{{gen &#x27;plan&#x27; max_tokens=500}}'>Your plan to join a book club to stay motivated and accountable for reading more books is a great idea. Here&#x27;s an elaboration on your plan and some steps to help you accomplish it:\n",
       "\n",
       "1. Research book clubs in your area: Start by looking for local book clubs in your community. You can search online, check local libraries, community centers, or bookstores for any book clubs that meet regularly. You can also ask friends or colleagues if they know of any book clubs you can join.\n",
       "\n",
       "2. Choose the right book club: When selecting a book club, consider factors such as the genre of books they read, the frequency of meetings, and the location. Make sure the book club aligns with your interests and schedule.\n",
       "\n",
       "3. Join online book clubs: If you can&#x27;t find a suitable book club in your area or prefer a more flexible schedule, consider joining an online book club. There are numerous online book clubs available on platforms like Goodreads, Facebook, and Reddit. These clubs allow you to participate in discussions and share your thoughts on books at your own pace.\n",
       "\n",
       "4. Set reading goals: Once you&#x27;ve joined a book club, set personal reading goals to help you stay on track. This could be a specific number of books per month or a certain amount of reading time per day. Keep track of your progress and adjust your goals as needed.\n",
       "\n",
       "5. Engage in discussions: Actively participate in book club discussions, whether in-person or online. Share your thoughts and opinions on the books you read, and listen to the perspectives of others. Engaging in discussions will not only help you better understand the books but also keep you motivated to read more.\n",
       "\n",
       "6. Make reading a habit: Incorporate reading into your daily routine. Set aside a specific time each day for reading, such as before bed or during your morning commute. Creating a reading habit will make it easier to achieve your goals.\n",
       "\n",
       "7. Stay accountable: Share your reading goals and progress with your book club members or friends. This will help you stay accountable and motivated to continue reading.\n",
       "\n",
       "8. Explore different genres: To keep things interesting, try reading books from various genres and authors. This will expose you to new ideas and perspectives, making your reading experience more enjoyable and enriching.\n",
       "\n",
       "9. Be patient and persistent: Reading more books may take time and effort, especially if you&#x27;re not used to reading regularly. Be patient with yourself and stay persistent in your efforts to read more.\n",
       "\n",
       "By following these steps, you</span></div></div></span></pre></div>\n",
       "<script type=\"text/javascript\">(()=>{var t={296:(t,e,n)=>{var i=NaN,o=\"[object Symbol]\",r=/^\\s+|\\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,c=/^0o[0-7]+$/i,d=parseInt,u=\"object\"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,l=\"object\"==typeof self&&self&&self.Object===Object&&self,f=u||l||Function(\"return this\")(),h=Object.prototype.toString,p=Math.max,m=Math.min,g=function(){return f.Date.now()};function b(t){var e=typeof t;return!!t&&(\"object\"==e||\"function\"==e)}function y(t){if(\"number\"==typeof t)return t;if(function(t){return\"symbol\"==typeof t||function(t){return!!t&&\"object\"==typeof t}(t)&&h.call(t)==o}(t))return i;if(b(t)){var e=\"function\"==typeof t.valueOf?t.valueOf():t;t=b(e)?e+\"\":e}if(\"string\"!=typeof t)return 0===t?t:+t;t=t.replace(r,\"\");var n=s.test(t);return n||c.test(t)?d(t.slice(2),n?2:8):a.test(t)?i:+t}t.exports=function(t,e,n){var i,o,r,a,s,c,d=0,u=!1,l=!1,f=!0;if(\"function\"!=typeof t)throw new TypeError(\"Expected a function\");function h(e){var n=i,r=o;return i=o=void 0,d=e,a=t.apply(r,n)}function v(t){var n=t-c;return void 0===c||n>=e||n<0||l&&t-d>=r}function _(){var t=g();if(v(t))return w(t);s=setTimeout(_,function(t){var n=e-(t-c);return l?m(n,r-(t-d)):n}(t))}function w(t){return s=void 0,f&&i?h(t):(i=o=void 0,a)}function j(){var t=g(),n=v(t);if(i=arguments,o=this,c=t,n){if(void 0===s)return function(t){return d=t,s=setTimeout(_,e),u?h(t):a}(c);if(l)return s=setTimeout(_,e),h(c)}return void 0===s&&(s=setTimeout(_,e)),a}return e=y(e)||0,b(n)&&(u=!!n.leading,r=(l=\"maxWait\"in n)?p(y(n.maxWait)||0,e):r,f=\"trailing\"in n?!!n.trailing:f),j.cancel=function(){void 0!==s&&clearTimeout(s),d=0,i=c=o=s=void 0},j.flush=function(){return void 0===s?a:w(g())},j}},777:t=>{var e,n,i=Math.max,o=(e=function(t,e){return function(t,e,n){if(\"function\"!=typeof t)throw new TypeError(\"Expected a function\");return setTimeout((function(){t.apply(void 0,n)}),1)}(t,0,e)},n=i(void 0===n?e.length-1:n,0),function(){for(var t=arguments,o=-1,r=i(t.length-n,0),a=Array(r);++o<r;)a[o]=t[n+o];o=-1;for(var s=Array(n+1);++o<n;)s[o]=t[o];return s[n]=a,function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}(e,this,s)});t.exports=o}},e={};function n(i){var o=e[i];if(void 0!==o)return o.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,n),r.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var i in e)n.o(e,i)&&!n.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},n.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(t){if(\"object\"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{\"use strict\";const t=t=>{const e=new Set;do{for(const n of Reflect.ownKeys(t))e.add([t,n])}while((t=Reflect.getPrototypeOf(t))&&t!==Object.prototype);return e};function e(e,{include:n,exclude:i}={}){const o=t=>{const e=e=>\"string\"==typeof e?t===e:e.test(t);return n?n.some(e):!i||!i.some(e)};for(const[n,i]of t(e.constructor.prototype)){if(\"constructor\"===i||!o(i))continue;const t=Reflect.getOwnPropertyDescriptor(n,i);t&&\"function\"==typeof t.value&&(e[i]=e[i].bind(e))}return e}var i=n(777),o=n.n(i),r=n(296),a=n.n(r);class s{constructor(t,n){e(this),this.interfaceId=t,this.callbackMap={},this.data={},this.pendingData={},this.jcomm=new c(\"guidance_interface_target_\"+this.interfaceId,this.updateData,\"open\"),this.debouncedSendPendingData500=a()(this.sendPendingData,500),this.debouncedSendPendingData1000=a()(this.sendPendingData,1e3),n&&o()(n)}send(t,e){this.addPendingData(t,e),this.sendPendingData()}sendEvent(t){for(const e of Object.keys(t))this.addPendingData(e,t[e]);this.sendPendingData()}debouncedSendEvent500(t){for(const e of Object.keys(t))this.addPendingData(e,t[e]);this.debouncedSendPendingData500()}debouncedSend500(t,e){this.addPendingData(t,e),this.debouncedSendPendingData500()}debouncedSend1000(t,e){this.addPendingData(t,e),this.debouncedSendPendingData1000()}addPendingData(t,e){Array.isArray(t)||(t=[t]);for(const n in t)this.pendingData[t[n]]=e}updateData(t){t=JSON.parse(t.data);for(const e in t)this.data[e]=t[e];for(const e in t)e in this.callbackMap&&this.callbackMap[e](this.data[e])}subscribe(t,e){this.callbackMap[t]=e,o()((e=>this.callbackMap[t](this.data[t])))}sendPendingData(){this.jcomm.send_data(this.pendingData),this.pendingData={}}}class c{constructor(t,e,n=\"open\"){this._fire_callback=this._fire_callback.bind(this),this._register=this._register.bind(this),this.jcomm=void 0,this.callback=e,void 0!==window.Jupyter?\"register\"===n?Jupyter.notebook.kernel.comm_manager.register_target(t,this._register):(this.jcomm=Jupyter.notebook.kernel.comm_manager.new_comm(t),this.jcomm.on_msg(this._fire_callback)):void 0!==window._mgr&&(\"register\"===n?window._mgr.widgetManager.proxyKernel.registerCommTarget(t,this._register):(this.jcomm=window._mgr.widgetManager.proxyKernel.createComm(t),this.jcomm.open({},\"\"),this.jcomm.onMsg=this._fire_callback))}send_data(t){void 0!==this.jcomm?this.jcomm.send(t):console.error(\"Jupyter comm module not yet loaded! So we can't send the message.\")}_register(t,e){this.jcomm=t,this.jcomm.on_msg(this._fire_callback)}_fire_callback(t){this.callback(t.content.data)}}class d{constructor(t,n){e(this),this.id=t,this.comm=new s(t),this.comm.subscribe(\"append\",this.appendData),this.comm.subscribe(\"replace\",this.replaceData),this.comm.subscribe(\"event\",this.eventOccurred),this.element=document.getElementById(\"guidance-content-\"+t),this.stop_button=document.getElementById(\"guidance-stop-button-\"+t),this.stop_button.onclick=()=>this.comm.send(\"event\",\"stop\")}appendData(t){t&&(this.stop_button.style.display=\"inline-block\",this.element.innerHTML+=t)}replaceData(t){t&&(this.stop_button.style.display=\"inline-block\",this.element.innerHTML=t)}eventOccurred(t){\"complete\"===t&&(this.stop_button.style.display=\"none\")}}window._guidanceDisplay=function(t,e){return new d(t,e)}})()})();; window._guidanceDisplay(\"17eb2469-4a39-4409-941f-a533bcedfded\");</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import guidance\n",
    "import re\n",
    "\n",
    "# we use GPT-4 here, but you could use gpt-3.5-turbo as well\n",
    "guidance.llm = guidance.llms.OpenAI(\"gpt-4\")\n",
    "\n",
    "# a custom function we will call in the guidance program\n",
    "def parse_best(prosandcons, options):\n",
    "    best = int(re.findall(r'Best=(\\d+)', prosandcons)[0])\n",
    "    return options[best]\n",
    "\n",
    "# define the guidance program using role tags (like `{{#system}}...{{/system}}`)\n",
    "create_plan = guidance('''\n",
    "{{#system~}}\n",
    "You are a helpful assistant.\n",
    "{{~/system}}\n",
    "\n",
    "{{! generate five potential ways to accomplish a goal }}\n",
    "{{#block hidden=True}}\n",
    "{{#user~}}\n",
    "I want to {{goal}}.\n",
    "{{~! generate potential options ~}}\n",
    "Can you please generate one option for how to accomplish this?\n",
    "Please make the option very short, at most one line.\n",
    "{{~/user}}\n",
    "\n",
    "{{#assistant~}}\n",
    "{{gen 'options' n=5 temperature=1.0 max_tokens=500}}\n",
    "{{~/assistant}}\n",
    "{{/block}}\n",
    "\n",
    "{{! generate pros and cons for each option and select the best option }}\n",
    "{{#block hidden=True}}\n",
    "{{#user~}}\n",
    "I want to {{goal}}.\n",
    "\n",
    "Can you please comment on the pros and cons of each of the following options, and then pick the best option?\n",
    "---{{#each options}}\n",
    "Option {{@index}}: {{this}}{{/each}}\n",
    "---\n",
    "Please discuss each option very briefly (one line for pros, one for cons), and end by saying Best=X, where X is the best option.\n",
    "{{~/user}}\n",
    "\n",
    "{{#assistant~}}\n",
    "{{gen 'prosandcons' temperature=0.0 max_tokens=500}}\n",
    "{{~/assistant}}\n",
    "{{/block}}\n",
    "\n",
    "{{! generate a plan to accomplish the chosen option }}\n",
    "{{#user~}}\n",
    "I want to {{goal}}.\n",
    "{{~! Create a plan }}\n",
    "Here is my plan:\n",
    "{{parse_best prosandcons options}}\n",
    "Please elaborate on this plan, and tell me how to best accomplish it.\n",
    "{{~/user}}\n",
    "\n",
    "{{#assistant~}}\n",
    "{{gen 'plan' max_tokens=500}}\n",
    "{{~/assistant}}''')\n",
    "\n",
    "# execute the program for a specific goal\n",
    "out = create_plan(\n",
    "    goal='read more books',\n",
    "    parse_best=parse_best, # a custom python function we call in the program\n",
    "    echo=True # display live generation in the notebook\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr style=\"height: 1px; opacity: 0.5; border: none; background: #cccccc;\">\n",
    "<div style=\"text-align: center; opacity: 0.5\">Have an idea for more helpful examples? Pull requests that add to this documentation notebook are encouraged!</div>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "adatest",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
